package hn.cch.framework.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
import java.util.Map;
import java.util.Random;

public class JwtUtil {

    public static int KEY_LEN = 16;


    /**
     * 随机从字母大小写，数字，特殊字符中拼接一定长度的字符串
     *
     * @param length
     * @return
     */
    public static String randomString(int length) {
        //字母大小写，数字，特殊字符
        String string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*~,./?;:";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        //生产随机字符串
        for (int i = 0; i < length; i++) {
            sb.append(string.charAt(random.nextInt(string.length())));
        }
        return sb.toString();
    }

    /**
     * 生产满足包含字母大小写，数字，特殊字符四种符号的密码
     *
     * @param length
     * @return
     */
    public static String generatePassword(int length) {
        while (true) {
            String result = randomString(length);
            //校验生成的字符串是否满足包含字母大小写，数字，特殊字符四种符号
            if (result.matches(".*[a-z]+.*") && result.matches(".*[A-Z]+.*")
                    && result.matches(".*[0-9]+.*") && result.matches(".*[!@#$%^&*-_+=~,./;?:]+.*")) {
                // 校验通过就返回，否则就重新生成
                return result;
            }
        }

    }

    /**
     * 生成密钥
     *
     * @return
     */
    public static Key getKey() {
        String password = generatePassword(KEY_LEN);
        byte[] base64 = Base64.decodeBase64(password);
        SecretKey key = new SecretKeySpec(base64, 0, base64.length, "AES");
        return key;
    }

    /**
     * 构建token
     *
     * @param claims
     * @param expiration
     * @param password
     * @return
     */
    public static String buildToken(Map<String, Object> claims, Date expiration, String password) {
        return Jwts.builder().setId("000").setSubject("chench")
                .setIssuedAt(new Date()).setExpiration(expiration)
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, password).compact();
    }

    /**
     * 解析token
     *
     * @param token
     * @param password
     * @return
     */
    public static Claims parseToken(String token, String password) {
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(password).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }
}
